﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.BackgroundAudio;
using System.Windows.Threading;

namespace DoubanFMApp.Data
{
    public class BackgroundAudioBinding : FrameworkElement
    {
        private DispatcherTimer timer = new DispatcherTimer();

        public BackgroundAudioBinding()
        {
            timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            timer.Tick += new EventHandler(timer_Tick);
            BackgroundAudioPlayer.Instance.PlayStateChanged -= new EventHandler(Instance_PlayStateChanged);
            BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);
        }

        void timer_Tick(object sender, EventArgs e)
        {
            this.Position = BackgroundAudioPlayer.Instance.Position;
            this.Duration = BackgroundAudioPlayer.Instance.Track.Duration;
            if(this.CurrentState!=BackgroundAudioPlayer.Instance.PlayerState)
            {
                this.CurrentState = BackgroundAudioPlayer.Instance.PlayerState;
            }
            this.UnPosition = this.Duration - this.Position;
        }

        #region Property

        public TimeSpan Duration
        {
            get { return (TimeSpan)GetValue(DurationProperty); }
            set { SetValue(DurationProperty, value); }
        }

        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(BackgroundAudioBinding), new PropertyMetadata(OnDurationPropertyChanged));

        public TimeSpan Position
        {
            get { return (TimeSpan)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }

        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(TimeSpan), typeof(BackgroundAudioBinding), new PropertyMetadata(OnPositionPropertyChanged));

        public TimeSpan UnPosition
        {
            get { return (TimeSpan)GetValue(UnPositionProperty); }
            set { SetValue(UnPositionProperty, value); }
        }

        public static readonly DependencyProperty UnPositionProperty =
            DependencyProperty.Register("UnPosition", typeof(TimeSpan), typeof(BackgroundAudioBinding), new PropertyMetadata(OnUnPositionPropertyChanged));

        public PlayState CurrentState
        {
            get { return (PlayState)GetValue(CurrentStateProperty); }
            set { SetValue(CurrentStateProperty, value); }
        }

        public static readonly DependencyProperty CurrentStateProperty =
            DependencyProperty.Register("CurrentState", typeof(PlayState), typeof(BackgroundAudioBinding), new PropertyMetadata(OnCurrentStatePropertyChanged));

        public AudioTrack AudioTrack
        {
            get { return (AudioTrack)GetValue(AudioTrackProperty); }
            set { SetValue(AudioTrackProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AudioTrack.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AudioTrackProperty =
            DependencyProperty.Register("AudioTrack", typeof(AudioTrack), typeof(BackgroundAudioBinding), new PropertyMetadata(OnAudioTrackPropertyChanged));

        #endregion

        #region PropertyChanged

        private static void OnDurationPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            BackgroundAudioBinding sender = o as BackgroundAudioBinding;
            if (e.NewValue == e.OldValue) return;
            sender.SetDuration((TimeSpan)e.NewValue);
        }

        private static void OnPositionPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            BackgroundAudioBinding sender = o as BackgroundAudioBinding;
            if (e.NewValue == e.OldValue) return;
            sender.SetPosition((TimeSpan)e.NewValue);
        }

        private static void OnUnPositionPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            BackgroundAudioBinding sender = o as BackgroundAudioBinding;
            if (e.NewValue == e.OldValue) return;
            sender.SetUnduration((TimeSpan)e.NewValue);
        }

        private static void OnAudioTrackPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            BackgroundAudioBinding sender = o as BackgroundAudioBinding;
            if (e.NewValue == e.OldValue) return;
            sender.SetAudioTrack((AudioTrack)e.NewValue);
        }

        private static void OnCurrentStatePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            BackgroundAudioBinding sender = o as BackgroundAudioBinding;
            if (e.NewValue == e.OldValue) return;
            PlayState state = (PlayState)e.NewValue;
            if (state == PlayState.Playing)
            {
                BackgroundAudioPlayer.Instance.Play();
            }
            else
            {
                BackgroundAudioPlayer.Instance.Pause();
            }
        }

        #endregion

        private void Instance_PlayStateChanged(object sender, EventArgs e)
        {
            this.CurrentState = BackgroundAudioPlayer.Instance.PlayerState;
            if (this.CurrentState == PlayState.Playing)
            {
                timer.Start();
            }
            else
            {
                timer.Stop();
            }
        }

        #region Set Property Value

        private void SetPosition(TimeSpan position)
        {
            this.Position = position;
        }

        private void SetDuration(TimeSpan duration)
        {
            this.Duration = duration;
        }

        private void SetUnduration(TimeSpan unDuration)
        {
            this.UnPosition = unDuration;
        }

        private void SetAudioTrack(AudioTrack at)
        {
            this.AudioTrack = at;
        }

        #endregion
    }
}
